set(AVIF_LOCAL_AOM_GIT_TAG v3.10.0)
set(AVIF_LOCAL_AVM_GIT_TAG research-v8.0.0)

if(AVIF_CODEC_AVM)
    # Building the avm repository generates files such as "libaom.a" because it is a fork of aom,
    # so its build can be treated the same as aom
    set(AOM_PACKAGE_NAME avm)
    set(AOM_MESSAGE_PREFIX "libavif(AVIF_CODEC_AVM=LOCAL)")
else()
    set(AOM_PACKAGE_NAME aom)
    set(AOM_MESSAGE_PREFIX "libavif(AVIF_CODEC_AOM=LOCAL)")
endif()

set(AOM_EXT_SOURCE_DIR "${AVIF_SOURCE_DIR}/ext/${AOM_PACKAGE_NAME}")
set(LIB_FILENAME "${AOM_EXT_SOURCE_DIR}/build.libavif/${CMAKE_STATIC_LIBRARY_PREFIX}aom${CMAKE_STATIC_LIBRARY_SUFFIX}")

if(EXISTS "${LIB_FILENAME}")
    message(STATUS "${AOM_MESSAGE_PREFIX}: compiled library found at ${LIB_FILENAME}")
    add_library(aom STATIC IMPORTED GLOBAL)
    set_target_properties(aom PROPERTIES IMPORTED_LOCATION "${LIB_FILENAME}" AVIF_LOCAL ON)
    target_include_directories(aom INTERFACE "${AOM_EXT_SOURCE_DIR}")
    if(AVIF_CODEC_AVM)
        # ext/avm/aom/aom_encoder.h includes config/aom_config.h which is generated by the local build of avm.
        target_include_directories(aom INTERFACE "${AOM_EXT_SOURCE_DIR}/build.libavif")
    endif()

    # Add link dependency flags from the aom.pc file in ext/aom or ext/avm
    # by prepending the build directory to PKG_CONFIG_PATH and then calling
    # pkg_check_modules
    if(WIN32)
        set(ENV{PKG_CONFIG_PATH} "${AOM_EXT_SOURCE_DIR}/build.libavif;$ENV{PKG_CONFIG_PATH}")
    else()
        set(ENV{PKG_CONFIG_PATH} "${AOM_EXT_SOURCE_DIR}/build.libavif:$ENV{PKG_CONFIG_PATH}")
    endif()

    pkg_check_modules(_AOM QUIET aom)

    set(_AOM_PC_LIBRARIES "${_AOM_STATIC_LIBRARIES}")
    # remove "aom" so we only have library dependencies
    list(REMOVE_ITEM _AOM_PC_LIBRARIES "aom")
    # Work around crbug.com/aomedia/356153293: aom.pc has -lm in the
    # Libs.private field on all platforms, whether libm or m.lib exists or not.
    if(WIN32 OR APPLE)
        list(REMOVE_ITEM _AOM_PC_LIBRARIES "m")
    endif()

    # Add absolute paths to libraries
    foreach(_lib ${_AOM_PC_LIBRARIES})
        find_library(_aom_dep_lib_${_lib} ${_lib} HINTS ${_AOM_STATIC_LIBRARY_DIRS})
        target_link_libraries(aom INTERFACE ${_aom_dep_lib_${_lib}})
    endforeach()
else()
    message(STATUS "${AOM_MESSAGE_PREFIX}: compiled library not found at ${LIB_FILENAME}, using FetchContent")
    if(EXISTS "${AOM_EXT_SOURCE_DIR}")
        message(STATUS "${AOM_MESSAGE_PREFIX}: ext/${AOM_PACKAGE_NAME} found; using as FetchContent SOURCE_DIR")
        set(FETCHCONTENT_SOURCE_DIR_AOM "${AOM_EXT_SOURCE_DIR}")
        message(CHECK_START "${AOM_MESSAGE_PREFIX}: configuring ${AOM_PACKAGE_NAME}")
    else()
        message(CHECK_START "${AOM_MESSAGE_PREFIX}: fetching and configuring ${AOM_PACKAGE_NAME}")
    endif()

    # aom sets its compile options by setting variables like CMAKE_C_FLAGS_RELEASE using
    # CACHE FORCE, which effectively adds those flags to all targets. We stash and restore
    # the original values and call avif_set_aom_compile_options to instead set the flags on all aom
    # targets
    function(avif_set_aom_compile_options target config)
        string(REPLACE " " ";" AOM_C_FLAGS_LIST "${CMAKE_C_FLAGS_${config}}")
        string(REPLACE " " ";" AOM_CXX_FLAGS_LIST "${CMAKE_CXX_FLAGS_${config}}")
        foreach(flag ${AOM_C_FLAGS_LIST})
            target_compile_options(${target} PRIVATE $<$<COMPILE_LANGUAGE:C>:${flag}>)
        endforeach()
        foreach(flag ${AOM_CXX_FLAGS_LIST})
            target_compile_options(${target} PRIVATE $<$<COMPILE_LANGUAGE:CXX>:${flag}>)
        endforeach()

        get_target_property(sources ${target} SOURCES)
        foreach(src ${sources})
            if(src MATCHES "TARGET_OBJECTS:")
                string(REGEX REPLACE "\\$<TARGET_OBJECTS:(.*)>" "\\1" source_target ${src})
                avif_set_aom_compile_options(${source_target} ${config})
            endif()
        endforeach()
    endfunction()

    set(AOM_BINARY_DIR "${FETCHCONTENT_BASE_DIR}/${AOM_PACKAGE_NAME}-build")

    if(ANDROID_ABI)
        set(AOM_BINARY_DIR "${AOM_BINARY_DIR}/${ANDROID_ABI}")
    endif()

    if(AVIF_CODEC_AVM)
        FetchContent_Declare(
            libaom
            GIT_REPOSITORY "https://gitlab.com/AOMediaCodec/avm.git"
            BINARY_DIR "${AOM_BINARY_DIR}"
            GIT_TAG ${AVIF_LOCAL_AVM_GIT_TAG}
            GIT_PROGRESS ON
            GIT_SHALLOW ON
            UPDATE_COMMAND ""
        )
        # This will disable the tensorflow dependency.
        set(CONFIG_ML_PART_SPLIT 0 CACHE INTERNAL "")
    else()
        FetchContent_Declare(
            libaom URL "https://aomedia.googlesource.com/aom/+archive/${AVIF_LOCAL_AOM_GIT_TAG}.tar.gz" BINARY_DIR
                       "${AOM_BINARY_DIR}" UPDATE_COMMAND ""
        )
    endif()

    set(CONFIG_PIC 1 CACHE INTERNAL "")
    if(libyuv_FOUND)
        set(CONFIG_LIBYUV 0 CACHE INTERNAL "")
    else()
        set(CONFIG_LIBYUV 1 CACHE INTERNAL "")
    endif()
    set(CONFIG_WEBM_IO 0 CACHE INTERNAL "")
    set(ENABLE_DOCS 0 CACHE INTERNAL "")
    set(ENABLE_EXAMPLES 0 CACHE INTERNAL "")
    set(ENABLE_TESTDATA 0 CACHE INTERNAL "")
    set(ENABLE_TESTS 0 CACHE INTERNAL "")
    set(ENABLE_TOOLS 0 CACHE INTERNAL "")
    if(CMAKE_OSX_ARCHITECTURES STREQUAL "arm64")
        set(AOM_TARGET_CPU "arm64")
    endif()

    if(NOT libaom_POPULATED)
        # Guard against the project setting cmake variables that would affect the parent build
        # See comment above for avif_set_aom_compile_options
        foreach(_config_setting CMAKE_C_FLAGS CMAKE_CXX_FLAGS CMAKE_EXE_LINKER_FLAGS)
            foreach(_config_type DEBUG RELEASE MINSIZEREL RELWITHDEBINFO)
                set(${_config_setting}_${_config_type}_ORIG ${${_config_setting}_${_config_type}})
            endforeach()
        endforeach()

        avif_fetchcontent_populate_cmake(libaom)

        set(_aom_config RELEASE)
        if(CMAKE_BUILD_TYPE)
            string(TOUPPER ${CMAKE_BUILD_TYPE} _aom_config)
        endif()
        list(LENGTH CMAKE_CONFIGURATION_TYPES num_configs)
        if(${num_configs} GREATER 0)
            list(GET CMAKE_CONFIGURATION_TYPES 0 _aom_config_type)
            string(TOUPPER ${_aom_config_type} _aom_config)
        endif()
        avif_set_aom_compile_options(aom ${_aom_config})

        # Restore the variables.
        foreach(_config_setting CMAKE_C_FLAGS CMAKE_CXX_FLAGS CMAKE_EXE_LINKER_FLAGS)
            foreach(_config_type DEBUG RELEASE MINSIZEREL RELWITHDEBINFO)
                unset(${_config_setting}_${_config_type} CACHE)
                set(${_config_setting}_${_config_type} ${${_config_setting}_${_config_type}_ORIG})
                unset(${_config_setting}_${_config_type}_ORIG)
            endforeach()
        endforeach()
        unset(_config_type)
        unset(_config_setting)
    endif()

    # If we have libyuv, we disable CONFIG_LIBYUV so that aom does not include the libyuv
    # sources from its third-party vendor library. But we still want AOM to have libyuv, only
    # linked against this project's target. Here we update the value in aom_config.h and add libyuv
    # to AOM's link libraries
    if(libyuv_FOUND)
        file(READ ${AOM_BINARY_DIR}/config/aom_config.h AOM_CONFIG_H)
        if("${AOM_CONFIG_H}" MATCHES "CONFIG_LIBYUV 0")
            string(REPLACE "CONFIG_LIBYUV 0" "CONFIG_LIBYUV 1" AOM_CONFIG_H "${AOM_CONFIG_H}")
            file(WRITE ${AOM_BINARY_DIR}/config/aom_config.h "${AOM_CONFIG_H}")
        endif()
        target_link_libraries(aom PRIVATE $<TARGET_FILE:yuv::yuv>)
    endif()

    set_property(TARGET aom PROPERTY AVIF_LOCAL ON)
    target_include_directories(aom INTERFACE "${libaom_SOURCE_DIR}" ${AOM_BINARY_DIR})

    message(CHECK_PASS "complete")
endif()
